<template>
  <div class="shop_address">
    <el-select v-model="inputValue.provinceCode" class="item" placeholder="省" :key="0">
      <el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.code" />
    </el-select>

    <el-select v-model="inputValue.cityCode" class="item" placeholder="市" @click.stop :key="1">
      <el-option v-for="(item, index) in cityList" :key="index" :label="item.name" :value="item.code" />
    </el-select>
    <el-select v-model="inputValue.districtCode" class="item" placeholder="区" :key="2">
      <el-option v-for="item in districtList" :key="item.code" :label="item.name" :value="item.code" />
    </el-select>
  </div>
</template>

<script setup lang="ts">
import { ref, getCurrentInstance, watch, onMounted } from 'vue'
import ComponentHat from '@/plugins/type'
import { Region } from '@/types/response/third-party.ts'
import { RegionDataType, RegionLabelType, RegionCodeType } from '@/components/region/RegionType.ts'
import BatchWatch from '@/utils/BatchWatch'
const { $API } = <ComponentHat>getCurrentInstance().proxy

const props = defineProps({
  modelValue: {
    type: Object as () => RegionCodeType,
    default: {} as RegionCodeType
  },
  regionLabel: {
    type: Object as () => RegionLabelType,
    default: {} as RegionLabelType
  }
})
// 本地选择的信息（props.modelValue是父级的）
const inputValue = ref(new RegionDataType())
// 选择列表数据
const provinceList = ref<Region[]>([])
const cityList = ref<Region[]>([])
const districtList = ref<Region[]>([])
async function refreshCityList(provinceCode: string | number) {
  await $API.thirdParty.cityList(provinceCode).then((result) => {
    if (result.success) cityList.value = result.data
  })
}
async function refreshDistrictList(cityCode: string | number) {
  await $API.thirdParty.districtList(cityCode).then((result) => {
    if (result.success) districtList.value = result.data
  })
}
const batchWatch = new BatchWatch(false, [
  () =>
    // 监听省份改变
    watch(
      () => inputValue.value.provinceCode,
      (newProvinceCode: string) => {
        inputValue.value.cityCode = null
        inputValue.value.cityName = null
        triggerChangeEmitInput()

        if (newProvinceCode != null) refreshCityList(newProvinceCode)
      },
      { deep: true, immediate: false }
    ),
  // 监听市级改变
  () =>
    watch(
      () => inputValue.value.cityCode,
      (newCityCode: string) => {
        inputValue.value.districtCode = null
        inputValue.value.districtName = null
        triggerChangeEmitInput()
        if (newCityCode != null) refreshDistrictList(newCityCode)
      },
      { deep: true, immediate: false }
    ),
  // 监听区级改变
  () =>
    watch(
      () => inputValue.value.districtCode,
      () => triggerChangeEmitInput(),
      { deep: true, immediate: false }
    )
])
async function adaptation() {
  // 使监听器停止
  batchWatch.stop()
  // 查看初始数据，进行加载列表数据
  // 全国城市数据是一定要加载的
  await $API.thirdParty.provinceList().then((result) => {
    if (result.success) {
      provinceList.value = result.data
      inputValue.value.provinceCode = props.modelValue.provinceCode
    }
  })
  // 如果有provinceCode,那就加载cityList
  if (props.modelValue.provinceCode) {
    await refreshCityList(props.modelValue.provinceCode)
    inputValue.value.provinceCode = props.modelValue.provinceCode
  }
  // 如果有城市code,那就加载districtList
  if (props.modelValue.cityCode) {
    await refreshDistrictList(props.modelValue.cityCode)
    inputValue.value.cityCode = props.modelValue.cityCode
  }
  // 如果有区code,虽然不用加载后面的了，但还是要设置inputValue的区code
  inputValue.value.districtCode = props.modelValue.districtCode
  // 维护内部inputValue的label值
  codeChangeAfterMaintenanceLabel()
  // 维护并通知外部inputValue的label值
  emitRegionLabel()
  console.log('启动监视器前：', inputValue.value, props.modelValue)
  // 启动监听，监听选择的变化
  batchWatch.start()
}

onMounted(async () => {
  // 适应传入过来的值
  await adaptation()
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: RegionCodeType): void
  (e: 'update:regionLabel', value: RegionLabelType): void
}>()

function emitModelValueChange() {
  console.log('通知外部code改变', inputValue.value)
  // 更新外部from-codes
  emit(
    'update:modelValue',
    Object.assign(
      {} as RegionCodeType,
      Object.assign(props.modelValue, {
        provinceCode: inputValue.value.provinceCode,
        cityCode: inputValue.value.cityCode,
        districtCode: inputValue.value.districtCode
      })
    )
  )
}
function emitRegionLabel() {
  console.log('通知外部label改变', inputValue.value)
  // 更新外部from-labels
  emit(
    'update:regionLabel',
    Object.assign(props.regionLabel, {
      provinceName: inputValue.value.provinceName,
      cityName: inputValue.value.cityName,
      districtName: inputValue.value.districtName
    })
  )
}

// 触发通知值(value与label)改变
function triggerChangeEmitInput() {
  // 维护内部inputValue的label值
  codeChangeAfterMaintenanceLabel()
  emitModelValueChange()
  emitRegionLabel()
}
function codeChangeAfterMaintenanceLabel() {
  for (let province of provinceList.value) {
    if (province.code === inputValue.value.provinceCode) {
      inputValue.value.provinceName = province.name
      break
    }
  }
  for (let city of cityList.value) {
    if (city.code === inputValue.value.cityCode) {
      inputValue.value.cityName = city.name
      break
    }
  }
  for (let district of districtList.value) {
    if (district.code === inputValue.value.districtCode) {
      inputValue.value.districtName = district.name
      break
    }
  }
}

defineExpose({
  adaptation
})
</script>

<style lang="scss" scoped>
.shop_address {
  display: flex;
  width: 100%;

  .item {
    // min-width: 120px;
    flex-grow: 1;
  }
}
</style>
